Notas clase 1: Introducción a R

Curso: Metodología Cuantitativa.
Magíster en Trabajo Social, Pontificia Universidad Católica de Chile.

Autor/a

Sebastián Rojas Vergara

Logo PUC

Bases

En el siguiente documento se presentan aspectos importanes sobre vectores y matrices, así como una introducción a los dataframes y tibbles.

Comenzaremos cargando el paquete tidyverse, el cual será necesario para llamar a la función tibble que se usará más adelante.

library(tidyverse)

1 Vectores

Los vectores son arreglos unidimensionales que solo pueden contener un tipo de dato.

1.1 Crear vectores

Los vectores se definen escribiendo c(), que viene del inglés combine. Cada uno de los elementos del vector se indican separando por coma. Se puede crear un objeto para guardar ese vector asignándole un nombre seguido de <-, como se muestra a continuación:

nombre_objeto <- c() # Adentro van los elementos del vector

Por ejemplo, en los siguientes casos se definen tres vectores que corresponden a tres tipos de datos revisados en clases: numeric, character y logical. Estos cumplen con el requisito de tener solamente datos de un mismo tipo.

Vector con elementos de tipo numérico

# Definiendo mi primer vector numérico
v_numerico <- c(1, 3, 5, 7, 9)

Además, en el caso de los vectores numéricos se puede indicar una secuencia utilizando la notación de dos puntos :.

# Entrega un vector con valores del 1 al 5
v_numerico_1 <- c(1:5)
v_numerico_1 
[1] 1 2 3 4 5

O de igual forma se pueden combinar secuencias con números específicos y otra secuencia. Las secuencias pueden ser incrementales o decrementales.

# Entrega un vector con valores del 1 al 5, 9 al 7 y el número 256
v_numerico_2 <- c(1:5, 9:7, 256)
v_numerico_2 
[1]   1   2   3   4   5   9   8   7 256

Vector con elementos de tipo caracter.

# Definiendo mi primer vector de caracteres
v_caracteres <- c("Hola Magíster de Trabajo Social", "Año 2023")

Vector con elementos de tipo lógico.

# Definiendo mi primer vector logico
v_logico <- c(TRUE, FALSE, TRUE, FALSE, TRUE)

Se puede comprobar que el elemento definido es un vector utilizando la función is.vector(). Esta recibe como argumento (lo que va dentro del paréntesis) el nombre del objeto. Si es un vector, retornará TRUE, y si no lo es, devolverá FALSE.

# Comprobando que es un vector
is.vector(v_numerico)
[1] TRUE

Para cualquier vector es posible obtener su largo, es decir, el número de elementos que contiene, usando la función length(). Esta función retornará el valor que corresponde al largo de ese vector.

En el caso del vector numérico de ejemplo, este consta de 5 elementos.

# Obteniendo el largo del vector
length(v_numerico)
[1] 5

Podemos comprobar el tipo de dato del vector utilizando las funciones class() y typeof()

  • La función class() devuelve la clase del objeto.
  • La función typeof() determina el método interno que usa R para guardar ese objeto.
# Comprobamos la clase del vector numérico
class(v_numerico)
[1] "numeric"
typeof(v_numerico)
[1] "double"
# Comprobamos la clase del vector de caracteres
class(v_caracteres)
[1] "character"
typeof(v_caracteres)
[1] "character"
# Comprobamos la clase del vector lógico
class(v_logico)
[1] "logical"
typeof(v_logico)
[1] "logical"

Los vectores pueden elementos vacíos que se denotan como NA, que es un acrónimo de Not Available. Esto se utiliza para indicar la ausencia de un valor. Si el valor NA está definido en el vector, este contará como un elemento más.

# Definiendo un vector numérico con NA
v_numerico_na <- c(5, 10, 33, 77, 101, 256, 5, NA, NA)
# Definiendo un vector de caracteres con NA
v_caracteres_na <- c("Hola", "Primera Clase", NA)
# Definiendo un vector lógico con NA
v_logico_na <- c(TRUE, FALSE, NA)
length(v_numerico_na)
[1] 9
length(v_caracteres_na)
[1] 3
length(v_logico_na)
[1] 3

1.2 Acceso a elementos

Cada elemento de un vector tiene una posición asignada, comenzando desde el 1. Para acceder a la posición del vector indicaremos el nombre del vector, seguido de paréntesis cuadrados [] (i.e. nombre_objeto[]).

Por ejemplo, podemos acceder al segundo elemento del vector numérico y del vector de caracteres.

# Acceder a la segunda posición
v_numerico[2]
[1] 3
v_caracteres[2]
[1] "Año 2023"

Utilizando el símbolo de dos puntos : se puede indicar un rango de posiciones del vector a las que se quiere acceder.

# Acceder a las tres primeras posiciones del vector
v_numerico[1:3]
[1] 1 3 5

De igual forma, se pueden utilizar otras funciones de R para acceder a posiciones del vector. Por ejemplo, la función length() devuelve el largo de un vector (también funciona para otras estructuras de datos)

# Accede siempre a la última posición sin conocer a priori su largo
v_numerico[length(v_numerico)]
[1] 9

Y si se quiere acceder a la penúltima posición, basta con obtener el largo del vector y restarle 1.

# Accede siempre a la penúltima posición sin conocer a priori su largo.
v_numerico[length(v_numerico) - 1]
[1] 7

En caso de acceder a una posición que no esté definida, el programa indicará un valor vacío denonado por NA

# Notar que en el vector definido no existe la posición 3
v_caracteres[3]
[1] NA

1.3 Modificar o eliminar elementos

Dado un vector ya creado, es posible modificar o eliminar elementos de este. Si se desea eliminar, se debe anteponer un signo menos - indicando la posición que se quiere eliminar.

En el ejemplo a continuación definimos usando un vector usando la función seq, que corresponde a una secuencia que toma tres argumentos:

  • from: indica el comienzo de la secuencia
  • to: indica el final de la secuencia
  • by: indica el incremento de la secuencia
v_completo <- seq(from = 10, to = 50, by = 10)
v_completo 
[1] 10 20 30 40 50
# Ahora eliminaremos el elemento que corresponda a la quinta posición
v_cortado <- v_completo[-4]
v_cortado
[1] 10 20 30 50

Y ahora modificaremos el valor 50 para que pase a ser 90.

# Ahora al valor que corresponde a 50 le asignaremos el valor 90.
v_cortado[v_cortado == 50] <- 90
v_cortado
[1] 10 20 30 90
Nota

Existen muchas más operaciones para vectores, como ordenarlos, reemplazar texto, generar reglas de reemplazo, etc. Estas se irán revisando a lo largo del curso con las funciones del paquete tidyverse()

1.4 Combinar vectores

Se pueden agregar elementos a un vector ya existente. Para ello, se puede emplear emplear la misma notación c():

# Combinando vectores

mi_vector <- c("Los juegos")
mi_vector <- c(mi_vector, "del hambre")
# Notar que ahora este vector tiene dos elementos
mi_vector
[1] "Los juegos" "del hambre"

También se pueden crear vectores que son combinaciones de vectores

# Creando vectores a partir de combinaciones de vectores
mi_vector_1 <- c(1, 3, 5, 7)
mi_vector_2 <- c(2, 4, 6, 8)
mi_vector_3 <- c(mi_vector_1, mi_vector_2)
mi_vector_3
[1] 1 3 5 7 2 4 6 8

1.5 Coerción

Cuando se crean o combinan vectores que tipos de datos diferentes, R realizará un proceso de coerción automáticamente. Es decir, buscará convertir los datos al tipo más flexible, siguiente unas reglas de jerarquía. El caso más simple es cuando se tienen datos de tipo numeric y character, donde el programa forzará a que los datos sean de este último tipo.

# Al definirse tiene datos de distinto tipo
mi_vector_coercion <- c(40, "50 años", 33, "33") # Las comillas indican que es texto

# Pero R genera una coerción
class(mi_vector_coercion)
[1] "character"

1.6 Operaciones con vectores

También se pueden realizar operaciones matemáticas con los vectores, tales como sumas, multiplicaciones, restas, etc.

# Multiplicar el vector por 2
mi_vector_multiplicar <- c(2, 4, 6) * 2
mi_vector_multiplicar
[1]  4  8 12

Como se puede apreciar, la operación de multiplicar se está aplicando a cada uno de los elementos del vector.

Esto nos introduce a un concepto de R conocido como vectorización. Esto quiere decir que hay operaciones que se aplican a cada uno de los elementos.

La vectorización funciona con otras estructuras de datos que veremos a lo largo del curso. Intuitivamente, bastará conocer que cuando una operación se puede vectorizar, su tiempo de ejecución es muy rápido.

1.7 Reciclar vectores

Cuando dos vectores no tienen el mismo largo, R realizará un proceso que se conoce como reciclaje. Este consiste en que irá tomando cada uno de los valores del vector más corto para que operen con los elementos del vector que aún no tienen su “pareja”.

En el ejemplo que se presenta a continuación, se han sumado los valores del siguiente modo:

\[ \begin{gathered} \ 2 + 4 \\ \ 2 + 5 \\ \text{Se acaban los valores del primer vector} \\ \ 2 + 6 \\ \ 3 + 8 \\ \text{Se recicla el valor 2 y 3 del primer vector} \end{gathered} \]

# Vectores de distinto tipo
v_largo2 <- c(2, 3)
v_largo3 <- c(4, 5, 6, 8)
v_largo_com <- v_largo2 + v_largo3
v_largo_com
[1]  6  8  8 11

2 Matrices

Las matrices son arreglos bidisimensionales que solo pueden contener un tipo de dato. Las matrices son una estructura con forma rectangular, formada por filas y columnas.

2.1 Crear matrices

Se definen escribiendo matrix(). Al menos cuatro argumentos nos resultarán relevantes de las matrices:

  • data: indica el vector de datos de la matriz
  • nrow: indica el número de filas
  • ncol: indica el número de columnas
  • byrow: indica si el llenado es por filas o columnas. Por defecto viene en llenado por columnas.

Ejemplo de llenado por columnas

matriz_1 <- matrix(1:9, ncol = 3) # Llenado por columnas
matriz_1
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

Ejemplo de llenado por filas

matriz_2 <- matrix(1:9, ncol = 3, byrow = TRUE) # Llenado por filas
matriz_2
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

2.2 Crear matriz a partir de vectores

Es posible crear matrices a partir de la unión de vectores. Para ello se pueden usar las siguientes funciones:

  • cbind que viene de column bind (unión por columnas) donde cada vector corresponde a una columna.
  • rbind que viene de row bind (unión por filas)

Ejemplos:

v_parte_1 <- c(1:2)
v_parte_2 <- c(3:4)
v_parte_3 <- c(5:6)
v_parte_4 <- c(7:8)

matriz_columna <- cbind(v_parte_1, v_parte_2, v_parte_3, v_parte_4)
matriz_columna
     v_parte_1 v_parte_2 v_parte_3 v_parte_4
[1,]         1         3         5         7
[2,]         2         4         6         8
matriz_fila <- rbind(v_parte_1, v_parte_2, v_parte_3, v_parte_4)
matriz_fila 
          [,1] [,2]
v_parte_1    1    2
v_parte_2    3    4
v_parte_3    5    6
v_parte_4    7    8

2.3 Acceso a elementos

En R las matrices siempre siguen el orden (filas, columnas). Con esta lógica se puede seleccionar sus elementos:

\[ \begin{gathered} \ \text{matriz}[i,j] \end{gathered} \] \[ \begin{aligned} \text{Donde:} \\ \ \text{matriz}[i,] = \text{selecciona la \textbf{fila} i-ésima de la matriz.} \\ \ \text{matriz}[, j] = \text{selecciona la \textbf{columna} j-ésima de la matriz.} \\ \ \text{matriz}[i, j] = \text{selecciona el j-ésimo elemento de la i-ésima fila} \end{aligned} \]

Realicemos un ejemplo con la matriz_2

matriz_2[1, 1] # Estoy seleccionando la fila 1 columna 1
[1] 1
matriz_2[2, 1] # Estoy seleccionando la fila 2 columna 1
[1] 4
matriz_2[1, ] # Estoy seleccionando a toda la fila 1
[1] 1 2 3
matriz_2[3, ] # Estoy seleccionando a toda la fila 3
[1] 7 8 9
matriz_2[, 1] # Estoy seleccionando a toda la columna 1
[1] 1 4 7

3 Dataframes y tibbles

3.1 Generando dataframes y tibbles

En R los dataframes son arreglos de datos bidimensionales (filas y columnas), pero que permiten distintos tipos de datos.

Es el caso usual de datos estructurados que se ven en los cursos de análisis de datos: las filas representan observaciones y las columnas variables.

Los tibbles son muy similares a los dataframe, pero con mejoras de calidad de vida. La función proviene del paquete tidyverse.

Los dataframes se generan a través de la función data.frame(), mientras que los tibbles con tibble().

# Se definen los vectores de datos
nombre <- c("Constanza", "Sofia", "Gonzalo")
carrera <- c("Ingeniería", "Administración", "Arqueología")
gen <- c(2013, 2018, 2023)
# Generando una base de datos con data.frame()
data_estudiantes_df <- data.frame(nombre, carrera, gen)
data_estudiantes_df
     nombre        carrera  gen
1 Constanza     Ingeniería 2013
2     Sofia Administración 2018
3   Gonzalo    Arqueología 2023
# Generando una base de datos con tibble()
data_estudiantes_tb <- tibble(nombre, carrera, gen)
data_estudiantes_tb
# A tibble: 3 × 3
  nombre    carrera          gen
  <chr>     <chr>          <dbl>
1 Constanza Ingeniería      2013
2 Sofia     Administración  2018
3 Gonzalo   Arqueología     2023

3.2 Acceder a elementos

En los tibbles y dataframes uno también puede seleccionar directamente filas o columnas. Para ello, existen dos opciones:

  • Usar la notación de $ para acceder a columnas específicas.

  • Usar la notación de [[]] para acceder a columnas específicas.

  • Usar la notación de matrices [i, j] para acceder a filas y columnas.

nombre_base$nombre_variable
nombre_base[i, j]
nombre_base[[]]

Ejemplos:

data_estudiantes_tb$nombre # accedemos a la columna nombre con $. Esto devuelve un vector
[1] "Constanza" "Sofia"     "Gonzalo"  
data_estudiantes_tb["nombre"] # accedemos a la columna nombre con []. Esto devuelve un tibble
# A tibble: 3 × 1
  nombre   
  <chr>    
1 Constanza
2 Sofia    
3 Gonzalo  
data_estudiantes_tb[["nombre"]] # accedemos a la columna nombre con[[]] Esto devuelve un vector
[1] "Constanza" "Sofia"     "Gonzalo"  
data_estudiantes_tb[[1]] # accedemos a la columna nombre con notación por posición [[]]
[1] "Constanza" "Sofia"     "Gonzalo"  
data_estudiantes_tb[1, "nombre"] # accedemos a la fila 1 de la columna nombre
# A tibble: 1 × 1
  nombre   
  <chr>    
1 Constanza
data_estudiantes_tb[1:2, "nombre"] # accedemos a la fila 1 y 2 de la columna nombre
# A tibble: 2 × 1
  nombre   
  <chr>    
1 Constanza
2 Sofia    
data_estudiantes_tb[[3, 1]] # Accedemos a la fila 3 para la columna 1. Retorna un vector
[1] "Gonzalo"
data_estudiantes_tb[3, 1] # Accedemos a la fila 3 para la columna 1. Retorna un tibble
# A tibble: 1 × 1
  nombre 
  <chr>  
1 Gonzalo
data_estudiantes_tb[1,] # Accedemos a toda la fila 1
# A tibble: 1 × 3
  nombre    carrera      gen
  <chr>     <chr>      <dbl>
1 Constanza Ingeniería  2013
data_estudiantes_tb[1,3] # Accedemos a la fila 1 columna 3
# A tibble: 1 × 1
    gen
  <dbl>
1  2013
data_estudiantes_tb[, -c(1)] # accedemos a todas las columnas menos nombre, por posición
# A tibble: 3 × 2
  carrera          gen
  <chr>          <dbl>
1 Ingeniería      2013
2 Administración  2018
3 Arqueología     2023
data_estudiantes_tb[, -c(1:2)] # accedemos a todas las columnas menos la 1 y la 2
# A tibble: 3 × 1
    gen
  <dbl>
1  2013
2  2018
3  2023
data_estudiantes_tb[, names(data_estudiantes_tb) != "nombre"] # accedemos a todas las columnas menos nombre
# A tibble: 3 × 2
  carrera          gen
  <chr>          <dbl>
1 Ingeniería      2013
2 Administración  2018
3 Arqueología     2023
data_estudiantes_tb[, !names(data_estudiantes_tb) %in% c("nombre", "carrera")]
# A tibble: 3 × 1
    gen
  <dbl>
1  2013
2  2018
3  2023